package org.university.service.impl;

import jakarta.persistence.criteria.Predicate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.university.entity.Student;
import org.university.enums.GlobalEnums;
import org.university.exception.ResourceNotFoundException;
import org.university.repository.StudentRepository;
import org.university.service.StudentService;

import javax.validation.ValidationException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.List;

@Service
public class StudentServiceImpl extends GenericServiceImpl<Student, String> implements StudentService {

    private static final Logger logger = LoggerFactory.getLogger(StudentServiceImpl.class);
    private final StudentRepository studentRepository;

    public StudentServiceImpl(StudentRepository repository, StudentRepository studentRepository) {
        super(repository);
        this.studentRepository = studentRepository;
    }

    @Transactional
    public void update(String id, Student student) {
        logger.info("更新学生ID: {}", student.getStudentId());
        if (student.getStudentId() != null && !studentRepository.existsById(student.getStudentId())) {
            throw new IllegalArgumentException("学生ID不存在: " + student.getStudentId());
        }

        Student updateStudent = studentRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("学生不存在，id: " + id));

        updateStudent.setStudentId(student.getStudentId());
        updateStudent.setStudentName(student.getStudentName());
        updateStudent.setGender(student.getGender());
        updateStudent.setBirthDate(student.getBirthDate());
        updateStudent.setEnrollmentDate(student.getEnrollmentDate());
        updateStudent.setDeptId(student.getDeptId());
        updateStudent.setClassId(student.getClassId());
        updateStudent.setPhone(student.getPhone());
        updateStudent.setEmail(student.getEmail());
        updateStudent.setAddress(student.getAddress());

        studentRepository.save(updateStudent);
        logger.info("ID为 {} 的学生信息更新成功", student.getStudentId());
    }

    @Override
    public Student save(Student student) {
        logger.info("保存学生ID: {}", student.getStudentId());
        if (student.getStudentId() != null && studentRepository.existsById(student.getStudentId())) {
            throw new IllegalArgumentException("学生ID已存在: " + student.getStudentId());
        }
        return studentRepository.save(student);
    }

    @Override
    public Page<Student> findAll(Pageable pageable) {
        logger.info("查询所有学生: 分页信息={}", pageable);
        return studentRepository.findByDeletedFalse(pageable);
    }

    @Override
    public Page<Student> searchStudents(String studentId, String studentName, String gender,
                                        String birthDate, String enrollmentDate, String deptId,
                                        String classId, String phone, String email, String address,
                                        Pageable pageable) {
        logger.info("多条件查询学生: 分页信息={}", pageable);
        return studentRepository.findAll((root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            predicates.add(cb.equal(root.get("deleted"), 0));

            if (StringUtils.hasText(studentId)) {
                predicates.add(cb.like(cb.lower(root.get("studentId")),
                        "%" + studentId.toLowerCase() + "%"));
            }

            if (StringUtils.hasText(studentName)) {
                predicates.add(cb.like(cb.lower(root.get("studentName")),
                        "%" + studentName.toLowerCase() + "%"));
            }

            if (StringUtils.hasText(gender)) {
                try {
                    GlobalEnums.Gender.valueOf(gender);
                    predicates.add(cb.equal(root.get("gender"), GlobalEnums.Gender.valueOf(gender)));
                } catch (IllegalArgumentException e) {
                    throw new ValidationException("无效的性别值，应为 '男' 或 '女'");
                }
            }

            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
            if (StringUtils.hasText(birthDate)) {
                try {
                    LocalDate date = LocalDate.parse(birthDate, formatter);
                    predicates.add(cb.equal(root.get("birthDate"), date));
                } catch (DateTimeParseException e) {
                    throw new ValidationException("无效的出生日期格式，应为 yyyy-MM-dd");
                }
            }

            if (StringUtils.hasText(enrollmentDate)) {
                try {
                    LocalDate date = LocalDate.parse(enrollmentDate, formatter);
                    predicates.add(cb.equal(root.get("enrollmentDate"), date));
                } catch (DateTimeParseException e) {
                    throw new ValidationException("无效的入学日期格式，应为 yyyy-MM-dd");
                }
            }

            if (StringUtils.hasText(deptId)) {
                try {
                    predicates.add(cb.equal(root.get("deptId"), Integer.parseInt(deptId)));
                } catch (NumberFormatException e) {
                    throw new ValidationException("无效的学院ID，应为整数");
                }
            }

            if (StringUtils.hasText(classId)) {
                try {
                    predicates.add(cb.equal(root.get("classId"), Integer.parseInt(classId)));
                } catch (NumberFormatException e) {
                    throw new ValidationException("无效的班级ID，应为整数");
                }
            }

            if (StringUtils.hasText(phone)) {
                predicates.add(cb.like(root.get("phone"), "%" + phone + "%"));
            }
            if (StringUtils.hasText(email)) {
                predicates.add(cb.like(root.get("email"), "%" + email + "%"));
            }
            if (StringUtils.hasText(address)) {
                predicates.add(cb.like(root.get("address"), "%" + address + "%"));
            }

            return cb.and(predicates.toArray(new Predicate[0]));
        }, pageable);
    }

    @Override
    public Page<Student> findAll() {
        logger.info("查询所有学生（无分页）");
        return studentRepository.findByDeletedFalse(Pageable.unpaged());
    }

    @Override
    public void deleteById(String id) {
        logger.info("删除学生ID: {}", id);
        studentRepository.findById(id).ifPresent(student -> {
            student.setDeleted(1);
            studentRepository.save(student);
        });
    }
}